<template>
  <div class="echart" ref="chartRef" v-loading="loading"></div>
</template>

<script setup>
import * as echarts from "echarts";
import { ref, computed, watch, onMounted, onBeforeUnmount, nextTick } from "vue";

// Props 定义
const props = defineProps({
  options: {
    type: Object,
    default: () => ({
      title: {
        text: "ECharts 示例",
      },
      tooltip: {},
      legend: {
        data: ["销量"],
      },
      xAxis: {
        data: ["类型一", "类型二", "类型三", "类型四", "类型五", "类型六"],
      },
      yAxis: {},
      series: [
        {
          name: "销量",
          type: "bar",
          data: [5, 20, 36, 10, 10, 20],
        },
      ],
    }),
  },
  autoResize: {
    type: Boolean,
    default: true,
  },
  theme: {
    type: String,
    default: "default",
  },
  initOptions: {
    type: Object,
    default: () => ({}),
  },
  loading: {
    type: Boolean,
    default: false,
  },
  loadingOptions: {
    type: Object,
    default: () => ({
      text: "数据加载中...",
      color: "#409EFF",
      textColor: "#000",
      maskColor: "rgba(255, 255, 255, 0.8)",
      zlevel: 0,
    }),
  },
  resizeDebounce: {
    type: Number,
    default: 300,
  },
  minHeight: {
    type: String,
    default: "400px",
  },
});

// Emits 定义
const emit = defineEmits([
  "chart-ready",
  "chart-updated",
  "chart-error",
  "chart-click",
  "chart-dblclick",
  "chart-mouseover",
  "chart-mouseout",
  "chart-datazoom",
  "chart-resized",
]);

// 响应式数据
const chartRef = ref();
const myChart = ref(null);
const resizeTimer = ref(null);

// 计算属性
const chartStyle = computed(() => ({
  width: "100%",
  height: "100%",
  minHeight: props.minHeight,
}));

// 监听器
watch(
  () => props.options,
  (newOptions) => {
    if (myChart.value && newOptions) {
      updateChart(newOptions);
    }
  },
  { deep: true }
);

watch(
  () => props.theme,
  () => {
    if (myChart.value) {
      reinitChart();
    }
  }
);

watch(
  () => props.loading,
  (isLoading) => {
    if (myChart.value) {
      if (isLoading) {
        myChart.value.showLoading(props.loadingOptions);
      } else {
        myChart.value.hideLoading();
      }
    }
  },
  { immediate: true }
);

// 方法定义
const initEcharts = async () => {
  try {
    if (!chartRef.value) {
      console.error("ECharts: 图表容器未找到");
      return;
    }

    // 如果已存在实例，先销毁
    if (myChart.value) {
      myChart.value.dispose();
    }

    // 初始化图表实例
    myChart.value = echarts.init(chartRef.value, props.theme, props.initOptions);

    // 设置图表配置
    updateChart(props.options);

    // 设置加载状态
    if (props.loading) {
      myChart.value.showLoading(props.loadingOptions);
    }

    // 绑定图表事件
    bindEvents();

    // 触发初始化完成事件
    emit("chart-ready", myChart.value);
  } catch (error) {
    console.error("ECharts 初始化失败:", error);
    emit("chart-error", error);
  }
};

const updateChart = (options) => {
  if (!myChart.value || !options) return;

  try {
    myChart.value.setOption(options, true);
    emit("chart-updated", myChart.value);
  } catch (error) {
    console.error("ECharts 更新失败:", error);
    emit("chart-error", error);
  }
};

const reinitChart = () => {
  if (myChart.value) {
    myChart.value.dispose();
    myChart.value = null;
  }
  initEcharts();
};

const bindEvents = () => {
  if (!myChart.value) return;

  // 绑定点击事件
  myChart.value.on("click", (params) => {
    emit("chart-click", params);
  });

  // 绑定双击事件
  myChart.value.on("dblclick", (params) => {
    emit("chart-dblclick", params);
  });

  // 绑定鼠标悬停事件
  myChart.value.on("mouseover", (params) => {
    emit("chart-mouseover", params);
  });

  // 绑定鼠标离开事件
  myChart.value.on("mouseout", (params) => {
    emit("chart-mouseout", params);
  });

  // 绑定数据区域缩放事件
  myChart.value.on("datazoom", (params) => {
    emit("chart-datazoom", params);
  });
};

const addResizeListener = () => {
  window.addEventListener("resize", debouncedResize);
};

const debouncedResize = () => {
  if (resizeTimer.value) {
    clearTimeout(resizeTimer.value);
  }
  resizeTimer.value = setTimeout(() => {
    handleResize();
  }, props.resizeDebounce);
};

const handleResize = () => {
  if (myChart.value) {
    try {
      myChart.value.resize();
      emit("chart-resized", myChart.value);
    } catch (error) {
      console.error("ECharts resize 失败:", error);
    }
  }
};

const resize = () => {
  handleResize();
};

const getChart = () => {
  return myChart.value;
};

const getDataURL = (options = {}) => {
  if (!myChart.value) return null;

  const defaultOptions = {
    type: "png",
    pixelRatio: 1,
    backgroundColor: "#fff",
  };

  return myChart.value.getDataURL({ ...defaultOptions, ...options });
};

const clear = () => {
  if (myChart.value) {
    myChart.value.clear();
  }
};

const showLoading = (options = {}) => {
  if (myChart.value) {
    myChart.value.showLoading({ ...props.loadingOptions, ...options });
  }
};

const hideLoading = () => {
  if (myChart.value) {
    myChart.value.hideLoading();
  }
};

// 生命周期
onMounted(async () => {
  await nextTick();
  await initEcharts();
  if (props.autoResize) {
    addResizeListener();
  }
});

onBeforeUnmount(() => {
  try {
    // 清除定时器
    if (resizeTimer.value) {
      clearTimeout(resizeTimer.value);
      resizeTimer.value = null;
    }

    // 移除事件监听器
    if (props.autoResize) {
      window.removeEventListener("resize", debouncedResize);
    }

    // 销毁图表实例
    if (myChart.value) {
      myChart.value.dispose();
      myChart.value = null;
    }
  } catch (error) {
    console.error("ECharts 销毁失败:", error);
  }
});

// 暴露方法给父组件
defineExpose({
  resize,
  getChart,
  getDataURL,
  clear,
  showLoading,
  hideLoading,
  reinitChart,
  updateChart,
});
</script>

<style scoped>
.echart {
  width: 100%;
  height: 100%;
  position: relative;
}

/* 确保容器有最小高度，防止图表无法显示 */
.echart:empty::before {
  content: "";
  display: block;
  min-height: 400px;
}
</style>
